package com.util;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * xxx
 *
 * @author heyonghao
 * @date 2022/7/13
 */
public class LocalDateUtil {

    // df.parse() 转 Date类型

    /**
     * 获取当前时间
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String NowDateAll() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(new Date());
    }

    /**
     * 获取当前时间,无格式存数字
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String NowDateAllNumber() {
        return NowDateAll().replace("-", "").replace(":", "").replace(" ","");
    }

    /**
     * 获取当前时间,无格式存数字
     * @return yyyy-MM-dd
     */
    public static String NowDateNumber() {
        return NowDateYmd().replace("-", "").replace(" ","");
    }

    /**
     * 获取当前时间,无格式存数字
     * @return yyyy-MM-dd
     */
    public static String NowDateTimeNumber() {
        return NowDateYmdHms().replace("-", "").replace(":","").replace(" ","");
    }

    /**
     * 获取long型日期
     * @return
     */
    public static Long getLongDay(){
        return Long.parseLong(NowDateNumber());
    }

    /**
     * 获取long型日期,前或者后 day
     * @return
     */
    public static Long getLongDay(int day){
        return Long.parseLong(BeforeOrOldDate(day).replace("-", "").replace(" ",""));
    }


    /**
     * 获取long型日期时间
     * @return
     */
    public static Long getLongDayTime(){
        return Long.parseLong(NowDateTimeNumber());
    }

    /**
     * 获取long型月份
     * @return
     */
    public static Long getLongMonth(){
        return Long.parseLong(NowDateNumber().substring(0,NowDateNumber().length() - 2));
    }

    /**
     * 获取long型年份
     * @return
     */
    public static Long getLongYear(){
        String buyMonth = NowDateNumber().substring(0,NowDateNumber().length() - 2);
        return Long.parseLong(buyMonth.substring(0,buyMonth.length() - 2));
    }

    /**
     * 获取当前时间,无格式存数字
     * @return yyyy-MM-dd
     */
    public static String BeforeOrOldDateNumber(Integer count) {
        return BeforeOrOldDate(count).replace("-", "").replace(" ","");
    }

    /**
     * long日期转 ymd 日期
     * @param day
     * @return
     */
    public static String longDayToYmd(Long day) {
        StringBuilder start = new StringBuilder(String.valueOf(day));
        return start.insert(4, "-").insert(7, "-").toString();
    }

    /**
     * 获取当前时间
     * @return yyyy-MM-dd
     */
    public static String NowDateYmd() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(new Date());
    }

    /**
     * 获取当前时间
     * @return yyyy-MM-dd
     */
    public static String NowDateYm() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
        return df.format(new Date());
    }

    /**
     * 获取当前时间
     * @return yyyy-MM-dd
     */
    public static String NowDateYmdHms() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH");
        return df.format(new Date());
    }

    /**
     * 获取当前时间
     * @return HH:mm:ss
     */
    public static String NowDateHms() {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
        return df.format(new Date());
    }

    /**
     * 获取当前时间
     * @return xx-年-xx-月-xx-日
     */
    public static String NowDateChinese() {
        StringBuilder sb = new StringBuilder(NowDateYmd());
        StringBuilder replace = sb.replace(4, 5, "年").replace(7, 8, "月").append("日");
        return replace.toString();
    }

    /**
     * 获取当前时间,冒号格式
     * @return HH:mm:ss
     */
    public static String NowDateColon() {
        StringBuilder sb = new StringBuilder(NowDateAll());
        StringBuilder replace = sb.replace(13, 14, ":").replace(16, 17, ":");
        return replace.toString();
    }

    /**
     * 获取当前时间的，前,或，后几天
     * @param num 负数为 前.
     * @return yyyy-MM-dd
     */
    public static String BeforeOrOldDate(Integer num){
        Date date=new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, num);
        date = calendar.getTime();
        SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }


    /**
     * 获取当前时间的， 毫秒级时间戳
     * @return 时间戳
     */
    public static Long MilliTimestamp(){
        return System.currentTimeMillis();
    }

    /**
     * 获取当前时间的， 秒级时间戳
     * @return 时间戳
     */
    public static Long SecondTimestamp(){
        return System.currentTimeMillis() / 1000;
    }


    /**
     * 获取本月第一天
     * @return String
     */
    public static String firstDayOfMonth(){
        LocalDateTime date = LocalDateTime.now();
        LocalDateTime firstday = date.with(TemporalAdjusters.firstDayOfMonth());
        return firstday.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    /**
     * 获取本月最后一天
     * @return String
     */
    public static String lastDayOfMonth(){
        LocalDateTime date = LocalDateTime.now();
        LocalDateTime lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
        return lastDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    /**
     * 获取两个long型 日期 之间间隔天数
     * @param start 新日期
     * @param end   以前日期
     * @return
     */
    public static long longDaysBetween(Long start,Long end){
        LocalDate startDate =LocalDate.parse(String.valueOf(start), DateTimeFormatter.ofPattern("yyyyMMdd"));
        LocalDate endDate = LocalDate.parse(String.valueOf(end), DateTimeFormatter.ofPattern("yyyyMMdd"));
        return ChronoUnit.DAYS.between(endDate, startDate);
    }

    /**
     * 获取两日期之间间隔的天数
     *
     * @param start 较小的时间
     * @param end  较大的时间
     * @return 相差天数
     */
    public static long daysBetween(Date start, Date end) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate =LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(start), formatter);
        LocalDate endDate = LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(end), formatter);
        return ChronoUnit.DAYS.between(endDate, startDate);
    }

    /**
     * 检查当前时间在某个时间段内
     * @param startHour HH:mm
     * @param endHour   HH:mm
     * @return boolean
     */
    public static boolean isBetween(String startHour,String endHour){
        boolean result=false;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        LocalTime startLocal=LocalTime.parse(startHour, dateTimeFormatter);
        LocalTime endLocal=LocalTime.parse(endHour,dateTimeFormatter);
        //如果时间段为隔夜时间
        LocalTime localTime=LocalTime.now();
        if (startLocal.isAfter(endLocal)){
            if (localTime.isAfter(startLocal)){
                System.out.println("当前隔夜时间"+localTime+"开始时间："+startHour+"结束时间："+endHour);
                result=true;
            }
            if (localTime.isBefore(endLocal)){
                System.out.println("当前隔夜时间"+localTime+"开始时间："+startHour+"结束时间："+endHour);
                result=true;
            }
        }
        //如果时间段不是隔夜的
        if (startLocal.isBefore(endLocal)){
            if (localTime.isAfter(startLocal)&&localTime.isBefore(endLocal)){
                System.out.println("当前正常时间"+localTime+"开始时间："+startHour+"结束时间："+endHour);
                result=true;
            }
        }
        return result;
    }

    /**
     * 获取本周的时间范围
     * @return 返回长度为2的字符串集合，如：[2022-05-02, 2022-05-08 ]
     */
    public static List<Long> getCurrentWeek() {
        List<Long> dataList = new ArrayList<>(2);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        //设置周一为一周之内的第一天
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        Long monday = Long.parseLong(dateFormat.format(calendar.getTime()).replace("-", "").replace(" ",""));
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        Long sunday = Long.parseLong(dateFormat.format(calendar.getTime()).replace("-", "").replace(" ",""));
        dataList.add(monday);
        dataList.add(sunday);
        return dataList;
    }


    /**
     * 获取本月所有日期
     * @return List<String>
     */
    public static List<String> getCurMonthDays(){
        return getBetweenDate(firstDayOfMonth(),NowDateYmd());
    }

    /**
     *  获取两个日期之间的所有日期 (年月日)
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<String> getBetweenDate(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime()<=endDate.getTime()){
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate=calendar.getTime();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 获取某月所有日期
     * @param date 2022-08
     * @return 所有日期
     */
    public static List<String> getMonthDay(String date) {
        String pre = date.substring(5);
        List<String> list = getMonthFullDay(date);
        List<String> listDay = new ArrayList<>();
        for (String date1 : list) {
            listDay.add(pre+"/"+date1.substring(8, 10));
        }
        return listDay;
    }

    public static List<String> getMonthFullDay(String date) {
        List<String> fullDayList = new ArrayList<String>();
        int year = Integer.parseInt(date.substring(0, 4));
        int month = Integer.parseInt(date.substring(5, 7));
        // 所有月份从1号开始
        int day = 1;
        // 获得当前日期对象
        Calendar cal = Calendar.getInstance();
        // 清除信息
        cal.clear();
        cal.set(Calendar.YEAR, year);
        // 1月从0开始
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, day);
        int count = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        for (int j = 0; j <= (count - 1); ) {
            if (sdf.format(cal.getTime()).equals(getLastDay(year, month))) {
                break;
            }
            cal.add(Calendar.DAY_OF_MONTH, j == 0 ? +0 : +1);
            j++;
            fullDayList.add(sdf.format(cal.getTime()));
        }
        return fullDayList;
    }

    public static String getLastDay(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, 0);
        return sdf.format(cal.getTime());
    }

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");


    /**
     * 获取两个时间节点之间的月份列表
     */
    public static List<String> getMonthBetween(String minDate, String maxDate){
        ArrayList<String> result = new ArrayList<String>();
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

            Calendar min = Calendar.getInstance();
            Calendar max = Calendar.getInstance();
            min.setTime(sdf.parse(minDate));
            min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

            max.setTime(sdf.parse(maxDate));
            max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

            Calendar curr = min;
            while (curr.before(max)) {
                result.add(sdf.format(curr.getTime()));
                curr.add(Calendar.MONTH, 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取当前年的第一天
     * @return
     */
    public static String getCurrYearFirst(){
        Calendar currCal=Calendar.getInstance();
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR,currCal.get(Calendar.YEAR));
        Date time = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(time);
    }

}